package com.atguigu.crowd.mvc.config;

import com.atguigu.crowd.exception.LoginAcctAlreadyInUseException;
import com.atguigu.crowd.exception.LoginAcctAlreadyInUseForUpdateException;
import com.atguigu.crowd.exception.LoginFailedException;
import com.atguigu.crowd.util.CrowdUtil;
import com.atguigu.crowd.util.ResultEntity;
import com.google.gson.Gson;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

import static com.atguigu.crowd.constant.CrowdConstant.ATTR_NAME_EXCEPTION;

//表示当前的类是一个基于注解的异常处理器类
@ControllerAdvice
public class CrowdExceptionResolver {

    @ExceptionHandler(value = LoginAcctAlreadyInUseException.class)
    public ModelAndView LoginAcctAlreadyInUseException(
            LoginAcctAlreadyInUseException exception,
          HttpServletRequest request,
          HttpServletResponse response
    ) throws IOException {
        String viewName = "admin-add" ;
//        返回modelAndView
        return commonResolve(viewName,exception,request,response);
    }
    @ExceptionHandler(value = LoginAcctAlreadyInUseForUpdateException.class)
    public ModelAndView LoginAcctAlreadyInUseForUpdateException(
            LoginAcctAlreadyInUseForUpdateException exception,
          HttpServletRequest request,
          HttpServletResponse response
    ) throws IOException {
        String viewName = "system-error" ;
//        返回modelAndView
        return commonResolve(viewName,exception,request,response);
    }
    @ExceptionHandler(value = ArithmeticException.class)
    public ModelAndView resolveMathException(
          ArithmeticException exception,
          HttpServletRequest request,
          HttpServletResponse response
    ) throws IOException {
        String viewName = "system-error" ;
//        返回modelAndView
        return commonResolve(viewName,exception,request,response);
    }
    @ExceptionHandler(value = LoginFailedException.class)
    public ModelAndView resolveLoginFailedException(
            LoginFailedException exception,
          HttpServletRequest request,
          HttpServletResponse response
    ) throws IOException {
        String viewName = "admin-login" ;
//        返回modelAndView
        return commonResolve(viewName,exception,request,response);
    }

    private boolean requestType;

    //    将一个类的具体异常类型和方法关联起来
    @ExceptionHandler(value = NullPointerException.class)
    public ModelAndView resolveNullPointerException(
            //实际捕获到的异常类型
            NullPointerException exception,
            //当前请求对象
            HttpServletRequest request,
            HttpServletResponse response) throws IOException {
        String viewName = "system-error" ;
//        返回modelAndView
        return commonResolve(viewName,exception,request,response);
    }
    private ModelAndView commonResolve(String viewName,Exception exception,HttpServletRequest request,HttpServletResponse response) throws IOException {
        //判断请求的类型
        boolean requestType = CrowdUtil.judgeRequestType(request);
//        如果是Ajax请求
        if(requestType){
//            创建resultEntity对象
            ResultEntity<Object> resultEntity = ResultEntity.failed(exception.getMessage());
//            创建Gson对象
            Gson gson = new Gson();
//            将resultEntity对象转换为Json字符串
            String toJson = gson.toJson(resultEntity);
//            将JSON字符串作为响应体返回给浏览器
            response.getWriter().write(toJson);
//            由于上面已经通过原生的response对象返回了响应，所以不提供ModelAndView

        }
//        如果不是Ajax请求则创建MedelAndView对象
        ModelAndView modelAndView = new ModelAndView();
//        将exception对象存入模型
        modelAndView.addObject(ATTR_NAME_EXCEPTION,exception);
//        设置对应的视图名称/**/
        modelAndView.setViewName(viewName);
//        返回modelAndView
        return modelAndView ;
    }
}
